﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Engine.Mathematics
{
    
/**
 * Givens plane rotation
 */
public class GivensRotation {

    /**
     * Cosine and sine of the rotation angle. c = x / sqrt(x^2 + y^2), and s =
     * -y / sqrt(x^2 + y^2)
     */
    private double c;
    private double s;

    /**
     * Constructs a Givens plane rotation for a given 2-vector
     * 
     * @param x
     *            First component of the vector
     * @param y
     *            Second component of the vector
     */
    public GivensRotation(double x, double y) {
        double roe = Math.Abs(x) > Math.Abs(y) ? x : y;

        double scale = Math.Abs(x) + Math.Abs(y);
        if (scale != 0) {
            double xs = x / scale;
            double ys = y / scale;
            double r = scale * Math.Sqrt(xs * xs + ys * ys);
            if (roe < 0)
                r *= -1;
            c = x / r;
            s = y / r;
        } else {
            c = 1;
            s = 0;
        }
    }

    /**
     * Applies the Givens rotation to two elements in a matrix column
     * 
     * @param H
     *            Matrix to apply to
     * @param column
     *            Column index
     * @param i1
     *            Row index of seriesPercolationThreashold element
     * @param i2
     *            Row index of second element
     */
    public void apply(Matrix H, int column, int i1, int i2) {
        double temp = c * H[i1, column] + s * H[i2, column];
        H[i2, column] = -s * H[i1, column] + c * H[i2, column];
        H[i1, column] = temp;
    }

    /**
     * Applies the Givens rotation to two elements of a vector
     * 
     * @param x
     *            Vector to apply to
     * @param i1
     *            Index of seriesPercolationThreashold element
     * @param i2
     *            Index of second element
     */
    public void apply(Vector x, int i1, int i2) {
        
        double temp = c * x[i1] + s * x[i2];
        x[i2] = -s * x[i1] + c * x[i2];
        x[i1] = temp;
    }
}
}
